package com.quectel.business.contentaudit.local;

import cn.hutool.core.io.FileUtil;
import com.quectel.business.contentaudit.Validator;
import com.quectel.business.contentaudit.ValidatorContext;
import com.quectel.constant.core.forum.ForumConstants;
import com.quectel.constant.global.SystemConstants;
import com.quectel.core.module.forum.dto.ForumSensitiveDto;
import com.quectel.core.module.forum.service.ForumSensitiveService;
import com.quectel.util.common.MyFileUtils;
import com.quectel.util.common.POIUtils;
import com.quectel.util.common.Response;
import com.quectel.util.kit.CacheKit;
import com.quectel.util.kit.StorageKit;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.InputStream;
import java.util.*;
import java.util.function.LongFunction;

/**
 * @author zhangheng
 * @email nolan.zhang@quectel.com
 * @date 2023/5/15 15:14
 * @description new java file header...
 */
@Component
@Slf4j
public class LocalValidatorImpl implements Validator<ValidatorContext> {

    public static final int LOCAL = 0;

    @DubboReference
    private ForumSensitiveService forumSensitiveService;

    @Override
    public Response validate(ValidatorContext validatorContext) {
        Map<String, ACNode> trieMap =getCacheTrieMap(validatorContext.getTenantId());

        //缓存失效
        if (MapUtils.isEmpty(trieMap)) {
            trieMap = handleTrieMap(validatorContext.getTenantId());
            if (MapUtils.isEmpty(trieMap)) {
                return Response.ok();
            }
        }
        String check = SensitiveWordsFilter.check(trieMap, validatorContext.getText());
        if (StringUtils.isNotBlank(check)) {
            return Response.error("包含违禁信息:" + check);
        }

        log.debug("LocalValidatorImpl validate begin");
        return Response.ok();
    }

    @Override
    public int getPriority() {
        //优先级最高
        return LOCAL;
    }

    /**
     * 缓存失效处置
     * @return
     */
    @Override
    public Response invalidCache(ValidatorContext validatorContext) {
        CacheKit.invalidRedisCache(SENSITIVE_WORD_KEY_FUNC.apply(validatorContext.getTenantId()));
        return Response.ok();
    }

    private static final LongFunction<String> SENSITIVE_WORD_KEY_FUNC = t ->
            ForumConstants.SENSITIVE_WORD_CACHE + t;


    private Map<String, ACNode> getCacheTrieMap(Long tenantId) {
        return CacheKit.cacheToRedis(
                () -> handleTrieMap(tenantId),
                SENSITIVE_WORD_KEY_FUNC.apply(tenantId) ,
                24 * 60 * 60
        );
    }



    private Map<String, ACNode> handleTrieMap(Long tenantId) {
        List<ForumSensitiveDto> forumSensitiveDtos = forumSensitiveService.selectByTenantIdAndStatus(tenantId, SystemConstants.NORMAL);
        if (CollectionUtils.isEmpty(forumSensitiveDtos)) {
            return Collections.emptyMap();
        }
        Map<String, List<String>> stringListMap = new HashMap<>();
        for (ForumSensitiveDto forumSensitiveDto : forumSensitiveDtos) {
            String fileId = forumSensitiveDto.getFileId();
            List<String> worlds = new ArrayList<>();
            File tempFile = null;
            try (InputStream inputStream = StorageKit.getObject(fileId)) {
                tempFile = MyFileUtils.writeFileToTempDir(inputStream, forumSensitiveDto.getFileName(), true);
                if (tempFile.exists()) {
                    List<Map<Integer, String>> analysis = null;
                    analysis = POIUtils.analysis(FileUtil.getInputStream(tempFile), 0, 0);
                    if (CollectionUtils.isNotEmpty(analysis)) {
                        for (Map<Integer, String> integerStringMap : analysis) {
                            if (StringUtils.isNotBlank(integerStringMap.get(0))) {
                                worlds.add(integerStringMap.get(0));
                            }
                        }
                    }
                }
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            } finally {
                if (tempFile != null && tempFile.exists()) {
                    FileUtil.del(tempFile);
                }
            }
            stringListMap.put(forumSensitiveDto.getName(), worlds);

        }
        return SensitiveWordsFilter.sensitiveWord(stringListMap);
    }

}
